package ee.siimoliver.chat.GUI.dialogs;

import java.awt.Color;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.io.IOException;
import java.net.ServerSocket;

import javax.swing.BorderFactory;
import javax.swing.JButton;
import javax.swing.JDialog;
import javax.swing.JFrame;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JTextField;

import net.miginfocom.swing.MigLayout;
import ee.siimoliver.chat.GUI.ChatFrame;
import ee.siimoliver.chat.GUI.LoadingFrame;
import ee.siimoliver.chat.controllers.BusinessLogicController;
import ee.siimoliver.chat.server.WebServer;
import ee.siimoliver.chat.utils.ApplicationProperties;
import ee.siimoliver.chat.utils.ChatUtils;
import ee.siimoliver.chat.utils.Const;
import ee.siimoliver.chat.utils.JsonParser;

public class PropertiesDialog extends JDialog {

	private static final long serialVersionUID = 1L;
	private JTextField inputUsername;
	private JTextField inputPort;
	private JLabel lblUsername;
	private JLabel lblPort;
	private JButton btnSave;
	private JButton btnCancel;
	
	public PropertiesDialog(JFrame parent) {
		super(parent, Const.LBL_PROPERTIES);
		initFields();
		addProperties();
		addFields();
		pack();
		ChatUtils.centerWindow(this);
	}
    
	private void addProperties() {
		setDefaultCloseOperation(DO_NOTHING_ON_CLOSE);
//		setSize(300, 100);
		setUndecorated(true);
		((JPanel) getContentPane()).setBorder(BorderFactory.createLineBorder(Color.BLACK));
		btnSave.addActionListener(new SaveAction());
		btnCancel.addActionListener(new CancelAction());
		ChatUtils.mapActionToEnter(inputUsername, btnSave);
		ChatUtils.mapActionToEnter(inputPort, btnSave);
	}
	
    private void initFields() {
    	lblUsername = new JLabel(Const.LBL_USERNAME);
    	lblPort = new JLabel(Const.LBL_PORT);
    	inputUsername = new JTextField(9);
    	inputPort = new JTextField(9);
    	btnSave = new JButton(Const.LBL_SAVE);
    	btnCancel = new JButton(Const.LBL_CANCEL);
    }
    
    private void addFields() {
    	setLayout(new MigLayout("", "[grow, fill, sg]", "[grow, fill]"));
    	add(lblUsername);
    	add(inputUsername, "wrap");
    	add(lblPort);
    	add(inputPort, "wrap");
    	add(btnSave);
    	add(btnCancel);
    }
    
    public void fillInputFields() {
    	inputUsername.setText(ApplicationProperties.getInstance().getProperty(Const.PROP_USERNAME));
    	inputPort.setText(ApplicationProperties.getInstance().getProperty(Const.PROP_PORT));
    }
    
    private void switchToParent(String frameName) {
    	this.setVisible(false);
		getParent().setVisible(true);
		getParent().setEnabled(true);
		String title;
		try {
			title = frameName + " @" + ChatUtils.getMyIpPort();
		} catch (IOException e) {
			title = frameName + " @ no connection available!";
		}
		((JFrame) getParent()).setTitle(title);
    }
    
    private void savePropertiesStartServer(String username, String port, BusinessLogicController businessController,
    		LoadingFrame loadingFrame) throws IOException {
    	loadingFrame.switchLoadingText("Saving properties");
    	ApplicationProperties.PROPERTIES_FILE = Const.FILE_ROOT + username + Const.PROPERTIES_FILE_EXT;
		ApplicationProperties ap = ApplicationProperties.getInstance();
		JsonParser.createAndPopulateJsonFile(String.format(Const.USERS_TABLE_FILE, username));
		ap.setProperty(Const.PROP_USERNAME, username);
		ap.setProperty(Const.PROP_PORT, port);
		ap.storeProperties();
		if (businessController.isServerRunning()) {
			loadingFrame.switchLoadingText("Restarting server");
			System.out.println("restarting server");
			businessController.restartServer();
		} else {
			loadingFrame.switchLoadingText("Starting server");
			System.out.println("Starting server");
			new WebServer((ChatFrame) getParent());
			businessController.startServer();
		}
    }
    
    private class SaveAction implements ActionListener {
		@Override
		public void actionPerformed(ActionEvent arg0) {
			if (!inputPort.getText().matches("\\d+")) {
				JOptionPane.showMessageDialog(PropertiesDialog.this, "Invalid port!", Const.TXT_ERROR, JOptionPane.ERROR_MESSAGE);
			} else {
				final String username = inputUsername.getText().trim();
				final String port = inputPort.getText().trim();
				if (!username.isEmpty() && !port.isEmpty()) {
					try {
						ServerSocket ss = new ServerSocket(Integer.valueOf(port));
						ss.close();
						final BusinessLogicController businessController = ((ChatFrame) getParent()).getBusinessLogicController();
						LoadingFrame lf = new LoadingFrame(((ChatFrame) getParent()).getLoadingImages(), PropertiesDialog.this, false) {
							@Override
							protected void doInBackground() {
								try {
									if (ChatUtils.fileSystemHasFile(Const.FILE_ROOT, username + Const.PROPERTIES_FILE_EXT)) {
										switchLoadingText("Saving properties");
										ApplicationProperties.PROPERTIES_FILE = Const.FILE_ROOT + username + Const.PROPERTIES_FILE_EXT;
										ApplicationProperties ap = ApplicationProperties.getInstance();
										ap.setProperty(Const.PROP_USERNAME, username);
										ap.setProperty(Const.PROP_PORT, port);
										ap.storeProperties();
										if (businessController.isServerRunning()) {
											switchLoadingText("Restarting server");
											businessController.restartServer();
										} else {
											switchLoadingText("Starting server");
											businessController.startServer();
										}
										switchToParent(username);
									} else {
										switchLoadingText("Saving properties");
										ApplicationProperties.PROPERTIES_FILE = Const.FILE_ROOT + username + Const.PROPERTIES_FILE_EXT;
										ApplicationProperties ap = ApplicationProperties.getInstance();
										ap.setProperty(Const.PROP_USERNAME, username);
										ap.setProperty(Const.PROP_PORT, port);
										ap.storeProperties();
										if (businessController.isServerRunning()) {
											switchLoadingText("Restarting server");
											businessController.restartServer();
										} else {
											switchLoadingText("Starting server");
											businessController.startServer();
										}
										if (businessController.checkName(this, username)) {
											switchToParent(username);
										} else {
											ChatUtils.deleteFiles(String.format(Const.USERS_TABLE_FILE, username), ApplicationProperties.PROPERTIES_FILE);
											switchLoadingText("Stopping server");
											businessController.stopServer();
											JOptionPane.showMessageDialog(PropertiesDialog.this, "This username already exists!",
													Const.TXT_ERROR, JOptionPane.ERROR_MESSAGE);
											ChatFrame chatApplication = new ChatFrame();
											new WebServer(chatApplication);
											chatApplication.run();
											((JFrame) PropertiesDialog.this.getParent()).dispose();
										}
									}
								} catch (Exception e) {
									switchLoadingText("Stopping server");
									System.err.println("Error and now closing");
									businessController.stopServer();
									JOptionPane.showMessageDialog(PropertiesDialog.this, e.getMessage(), Const.TXT_ERROR, JOptionPane.ERROR_MESSAGE);
								}
							}
						};
						lf.execute();
					} catch (Exception e1) {
						JOptionPane.showMessageDialog(PropertiesDialog.this, e1.getMessage(),
								Const.TXT_ERROR, JOptionPane.ERROR_MESSAGE);
						return;
					}
				} else {
					JOptionPane.showMessageDialog(PropertiesDialog.this, "Input fields cannot be empty!", Const.TXT_ERROR, JOptionPane.ERROR_MESSAGE);
				}
			}
		}
    }
    
    private class CancelAction implements ActionListener {
    	@Override
		public void actionPerformed(ActionEvent arg0) {
    		BusinessLogicController businessController = ((ChatFrame) getParent()).getBusinessLogicController();
        	if (!businessController.isServerRunning()) {
				JOptionPane.showMessageDialog(PropertiesDialog.this, "Exiting application!", Const.TXT_ERROR, JOptionPane.ERROR_MESSAGE);
				System.exit(0);
//        		businessController.startServer();
        	}
			switchToParent(ApplicationProperties.getInstance().getProperty(Const.PROP_USERNAME));
		}
    }
}
